/*
	Copyright 2009 Benjamin Vedder	vedder87@gmail.com
	
	This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */

package com.google.code.retrobox.editor.tiles;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;

import javax.swing.*;

import com.google.code.retrobox.editor.dataCollections.TileData;


public class Tile extends JComponent {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	// TileSet configuration
	public static int	WIDTH = 8,
						HEIGHT = 8, 
						//TILES_PER_SET = 240,
						MAX_TILES_PER_SET = 256,
						TILE_BPP = 4;
	
	public static char	DEFAULT_TILE = 32;
	public static char	DEFAULT_COLOR = 0x00;
	
	
	// More static stuff
	private static Color gridColor = Color.white;
	private static boolean	drawGrid = true,
							highlight = false,
							showCollision = true;
	
	private List<ActionListener> listeners = new LinkedList<ActionListener>();
	public Tile self = this;
	
	
	private int 	SIDEX = 24,
					SIDEY = 24;
		
	private boolean mouseInside = false;
	
	private TileSetPanel tilePanel = null;
	
	private Color[] palette = {	new Color(Integer.parseInt( "000000",16)), 
								new Color(Integer.parseInt( "0000AA",16)),
								new Color(Integer.parseInt( "00AA00",16)),
								new Color(Integer.parseInt( "00AAAA",16)),
								new Color(Integer.parseInt( "AA0000",16)),
								new Color(Integer.parseInt( "AA00AA",16)),
								new Color(Integer.parseInt( "AA5500",16)),
								new Color(Integer.parseInt( "AAAAAA",16)),
								new Color(Integer.parseInt( "555555",16)),
								new Color(Integer.parseInt( "5555FF",16)),
								new Color(Integer.parseInt( "55FF55",16)),
								new Color(Integer.parseInt( "55FFFF",16)),
								new Color(Integer.parseInt( "FF5555",16)),
								new Color(Integer.parseInt( "FF55FF",16)),
								new Color(Integer.parseInt( "FFFF55",16)),
								new Color(Integer.parseInt( "FFFFFF",16))
								};
	
	private TileData 	currentTile, 
						hoverTile = null;
	
	public Tile(TileSetPanel pan, TileData d) {
		tilePanel = pan;
		currentTile = d;
		
		setPreferredSize(new Dimension(SIDEX, SIDEY));
		setOpaque(true);
		//setBorderPainted(false);
		setForeground(Color.DARK_GRAY);
		
		addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (tilePanel != null) {
					if (hoverTile != null) {
						currentTile = hoverTile;
					}
				}
			}
		});

		addMouseListener(new java.awt.event.MouseListener() {
			public void mouseEntered(java.awt.event.MouseEvent evt) {
				mouseInside = true;
				
				if (tilePanel != null) {
					hoverTile = tilePanel.getCurrentTile();
					repaint();
					validate();

					if (evt.isShiftDown()) {
						currentTile = hoverTile;
					}
				} else if (highlight) {
					repaint();
					validate();
				}
			}

			public void mouseExited(java.awt.event.MouseEvent evt) {
				mouseInside = false;

				if (tilePanel != null) {
					if (evt.isShiftDown()) {
						currentTile = hoverTile;
					}

					repaint();
					validate();
				} else if (highlight) {
					repaint();
					validate();
				}

			}


			public void mousePressed(MouseEvent arg0) {
				if (tilePanel != null && arg0.isPopupTrigger()) {
					tilePanel.setCurrentTile(currentTile);
				}
			}

			public void mouseReleased(MouseEvent arg0) {
				if (tilePanel != null && arg0.isPopupTrigger()) {
					tilePanel.setCurrentTile(currentTile);
				}
				
				if (mouseInside && arg0.getButton() == MouseEvent.BUTTON1) {
					for (ActionListener element: listeners) {
						element.actionPerformed(new ActionEvent(self, 0, "Mouse clicked"));
					}
				}
			}

			public void mouseClicked(MouseEvent arg0) {
				
			}

		});
	}
	
	public TileData getTileData() {
		return currentTile;
	}

	public void setTileSetPanel(TileSetPanel pan) {
		tilePanel = pan;
	}
	
	public static void setDrawGrid(boolean draw) {
		drawGrid = draw;
	}
	
	public static void setShowCollision(boolean draw) {
		showCollision = draw;
	}
	
	public void setHighlight (boolean b) {
		highlight = b;
	}
	
	public void setPixelsPerPixel(int x, int y) {
		SIDEX = x;
		SIDEY = y;
		setPreferredSize(new Dimension(SIDEX, SIDEY));
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		char[] pix;
		TileData tile;
		
		if (mouseInside && hoverTile != null) {
			tile = hoverTile;
		} else {
			tile = currentTile;
		}
		
		pix = tile.pixels;
		
		int 	W = SIDEX / WIDTH, 
				H = SIDEY / HEIGHT, 
				ind = 0;
		
		for (int i = 0;i < HEIGHT;i++) {
			for (int j = 0;j < WIDTH;j++) {
				Color c;
				int d;
				if ((ind % 2) != 0) {
					d = pix[ind / 2] & 0x000F;
				} else {
					d = pix[ind / 2] >>> 4;
				}
				
				c = palette[d];
				
				if (mouseInside && highlight) {
					int INCR = 0, INCG = 0, INCB = 0;
					
					if (c.getRed() < 220) {
						INCR = 35;
					}
					if (c.getGreen() < 220) {
						INCG = 35;
					}
					if (c.getBlue() < 220) {
						INCB = 35;
					}
					
					Color tmp = new Color( c.getRed()+INCR,
                            c.getGreen()+INCG,
                            c.getBlue()+INCB);
					c = tmp;
				}
				
				g.setColor(c);
				g.fillRect(j * W, i * H, W, H);
				ind++;
			}
		}
		
		if (drawGrid) {
			g.setColor(gridColor);
			g.fillRect(0, 0, 1, 1);
			g.fillRect((WIDTH * SIDEX) - 1, 0, 1, 1);
			g.fillRect(0, (HEIGHT * SIDEY) - 1, 1, 1);
			g.fillRect((WIDTH * SIDEX) - 1, (HEIGHT * SIDEY) - 1, 1, 1);
		}
		
		int lineThickness = 2;
		if (showCollision) {
			if (tile.collInfo.north) {
				g.setColor(Color.orange);
				g.fillRect(0, 0, SIDEX, lineThickness);
			}
			if (tile.collInfo.south) {
				g.setColor(Color.CYAN);
				g.fillRect(0, SIDEY - lineThickness, SIDEX, lineThickness);
			}
			if (tile.collInfo.east) {
				g.setColor(Color.orange);
				g.fillRect(SIDEX - lineThickness, 0, lineThickness, SIDEY);
			}
			if (tile.collInfo.west) {
				g.setColor(Color.CYAN);
				g.fillRect(0, 0, lineThickness, SIDEY);
			}
			if (tile.collInfo.water) {
				g.setColor(Color.blue);
				g.fillRect(SIDEX / 4, SIDEY / 4, SIDEX / 2, SIDEY / 2);
			}
			if (tile.collInfo.jump) {
				g.setColor(Color.red);
				g.fillRect(0, lineThickness, SIDEX, SIDEY / 3);
			}
		}
	}
	
	public void addActionListener(ActionListener w) {
		listeners.add(w);
	}
}



